/**
 * Project:mail-settings-detector
 * File:GuessDetector.java
 * Copyright 2004-2014 Homolo Co., Ltd. All rights reserved.
 */
package com.homolo.msd;

import org.apache.commons.lang.StringUtils;

import com.homolo.msd.MailSettings.ImapServer;
import com.homolo.msd.MailSettings.PopServer;
import com.homolo.msd.MailSettings.SmtpServer;
import com.homolo.msd.util.PortUtils;

/**
 * Try to guess the settings, base the experience.
 *
 * @author rory
 */
public class GuessDetector implements Detector {

    /**
     * The common <mail.example.com> 's prefix.
     */
    private static final String MAIL_DOMAIN_PREFIX = "mail.";

    /**
     * {@inheritDoc}
     */
    public MailSettings detect(String mail) {
        String domain = StringUtils.substringAfter(mail, "@");
        MailSettings settings = new MailSettings();
        settings.setPopServer(guessPopServer(domain));
        settings.setSmtpServer(guessSmtpServer(domain));
        settings.setImapServer(guessImapServer(domain));
        if (settings.getPopServer() == null && settings.getSmtpServer() == null && settings.getImapServer() == null) {
            return null;
        }
        return settings;
    }

    /**
     * Try to guess imap.example.com, mail.example.com domain's 993/143 port.
     *
     * @param domain the domain to guess
     * @return the ImapServer setting or null when can't guess
     */
    private ImapServer guessImapServer(String domain) {
        String[] hosts = new String[]{"imap." + domain, MAIL_DOMAIN_PREFIX + domain};
        for (String host : hosts) {
            if (PortUtils.isOpen(host, 993)) {
                return new ImapServer(host, 993, true);
            }
            if (PortUtils.isOpen(host, 143)) {
                return new ImapServer(host, 143, false);
            }
        }
        return null;
    }

    /**
     * Try to guess smtp.example.com, mail.example.com domain's 994/587/465 port.
     *
     * @param domain the domain to guess
     * @return the SmtpServer setting or null when can't guess
     */
    private SmtpServer guessSmtpServer(String domain) {
        String[] hosts = new String[]{"smtp." + domain, MAIL_DOMAIN_PREFIX + domain};
        for (String host : hosts) {
            if (PortUtils.isOpen(host, 994)) {
                return new SmtpServer(host, 994, true);
            }
            if (PortUtils.isOpen(host, 587)) {
                return new SmtpServer(host, 587, true);
            }
            if (PortUtils.isOpen(host, 465)) {
                return new SmtpServer(host, 465, true);
            }
            if (PortUtils.isOpen(host, 25)) {
                return new SmtpServer(host, 25, false);
            }
        }
        return null;
    }

    /**
     * Try to guess pop3.example.com, pop.example.com, mail.example.com domain's 995/110 port.
     *
     * @param domain the domain to guess
     * @return the PopServer setting or null when can't guess
     */
    private PopServer guessPopServer(String domain) {
        String[] hosts = new String[]{"pop3." + domain, "pop." + domain, MAIL_DOMAIN_PREFIX + domain};
        for (String host : hosts) {
            if (PortUtils.isOpen(host, 995)) {
                return new PopServer(host, 995, true);
            }
            if (PortUtils.isOpen(host, 110)) {
                return new PopServer(host, 110, false);
            }
        }
        return null;
    }

}
